/* ------------------------------------------------------------------- C++ OBJECT LIBRARY SOURCE CODE: vector Tom Annau ------------------------------------------------------------------- */ #include "vector.hh" #include #include /* ------------------------------------------------------------------- Constructors and destructor ------------------------------------------------------------------- */ vector::vector(int dimensions) { dims = dimensions; if (dims < 0) { cerr << "ERROR: Number of vector dimensions must be non-negative\n"; dims = 0; } if (dims == 0) value = NULL; else { value = new double[dimensions]; memset(value, 0, dims * sizeof(double)); } ref_counter = 0; } vector::vector(int dimensions, double *data) { if (dimensions > 0) { dims = dimensions; value = data; ref_counter = 1; } else { cerr << "ERROR: In vector constructor from array data, dimension " "must be positive\n"; value = NULL; dims = 0; ref_counter = 0; } } vector::vector(const vector& v) { dims = v.dims; if (dims > 0) { value = new double[dims]; memcpy(value, v.value, dims * sizeof(double)); } else value = NULL; ref_counter = 0; } vector::~vector(void) { if (!ref_counter) delete [] value; } /* ------------------------------------------------------------------- Assignment operators and type casts ------------------------------------------------------------------- */ vector& vector::operator = (const vector& v) { if (same_dimension_as(v)) memcpy(value, v.value, dims * sizeof(double)); return *this; } string vector::to_string(void) const return s; { if (dims) { for (int i = 0; i < dims - 1; i++) { s += string(value[i]); s += ", "; } s += string(value[i]); } } /* ------------------------------------------------------------------- Comparison operators ------------------------------------------------------------------- */ int vector::operator == (const vector& v) const { if (same_dimension_as(v)) return memcmp(value, v.value, dims * sizeof(double)) == 0; else return 0; } int vector::operator != (const vector& v) const { if (same_dimension_as(v)) return memcmp(value, v.value, dims * sizeof(double)) != 0; else return 0; } /* ------------------------------------------------------------------- Arithmetic with vectors and scalars ------------------------------------------------------------------- */ vector& vector::operator += (const vector& v) { if (same_dimension_as(v)) { for (register int i = 0; i < dims; *(value + i) += *(v.value + i++)); } return *this; } vector vector::operator - (void) const return r(*this); { for (register int i = 0; i < dims; *(r.value + i) = -*(value + i++)); } vector& vector::operator -= (const vector& v) { if (same_dimension_as(v)) { for (register int i = 0; i < dims; *(value + i) -= *(v.value + i++)); } return *this; } double dot(const vector& v1, const vector& v2) { double sum = 0; if (v1.same_dimension_as(v2)) { for (int i = 0; i < v1.dims; i++) sum += *(v1.value + i) * *(v2.value + i); } return sum; } /* ------------------------------------------------------------------- Miscellaneous methods ------------------------------------------------------------------- */ void vector::zero(void) { memset(value, 0, dims * sizeof(double)); } double vector::magnitude(void) const { double sum = 0.0, temp; for (register int i = 0; i < dims; sum += (temp = fabs(*(value + i++))) * temp); return sqrt(sum); } void vector::resize(int new_dimension) { if (new_dimension == dims) { memset(value, 0, dims * sizeof(double)); return; } if (ref_counter) { cerr << "ERROR: Cannot resize vector, pointing at unowned data\n"; return; } if (new_dimension < 0) { cerr << "ERROR: Cannot resize a vector to a negative dimension\n"; return ; } if (new_dimension == 0) { if (value) delete value; dims = 0; value = NULL; return; } if (value) delete [] value; dims = new_dimension; value = new double[dims]; memset(value, 0, dims * sizeof(double)); } void vector::upsize(int new_dimension) { if (ref_counter) { cerr << "ERROR: Cannot upsize vector, pointing at unowned data\n"; return; } if (new_dimension <= dims) { if (new_dimension == dims) return; cerr << "ERROR: Must upsize vector to larger dimension\n"; return; } if (new_dimension < 1) { cerr << "ERROR: Must upsize vector to positive dimension\n"; return ; } double *new_value = new double[new_dimension]; if (value) { memcpy(new_value, value, dims * sizeof(double)); delete [] value; value = new_value; } memset(new_value + dims, 0, (new_dimension - dims) * sizeof(double)); dims = new_dimension; } /* ------------------------------------------------------------------- Stream methods ------------------------------------------------------------------- */ ostream& operator << (ostream& out, const vector& v) { for (int i = 0; i < v.dims; i++) out << v[i] << CR; out << CR; return out; } istream& operator >> (istream& in, vector& v) { int index = 0; string input_line; while (!in.eof()) { if (index >= v.dims) { cerr << "ERROR: Vector from input stream too large to fit " "into existing vector\n"; return in; } in >> input_line; if (input_line[0] != '#' && !input_line.blank()) v.value[index++] = input_line.to_double(); else if (input_line.blank()) break; } if (index != v.dims) { cerr << "ERROR: Vector from input stream too small for " "existing vector\n"; } return in; } ostream& operator < (ostream& out, const vector& v) { return out.write(v.value, v.dims * sizeof(double)); } istream& operator > (istream& in, vector& v) { in.read(v.value, v.dims * sizeof(double)); return in; } /* ------------------------------------------------------------------- Protected methods ------------------------------------------------------------------- */ void vector::construct_from_string(string s) { if (s.blank()) { dims = 0; value = NULL; } else { dims = s.frequency(",") + 1; value = new double[dims]; for (int i = 0; i < dims - 1; i++) { value[i] = s.to_double(); s.drop_first_char(s.position(",") + 1); } value[i] = s.to_double(); } ref_counter = 0; }